package bma.common.thrift.servicehub;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.thrift.TProcessor;

import bma.common.langutil.core.ExceptionUtil;
import bma.common.langutil.core.SizeUtil;
import bma.common.langutil.core.SizeUtil.Unit;
import bma.common.langutil.core.ValueUtil;
import bma.common.langutil.io.HostPort;
import bma.common.thrift.ThriftClientConfig;

public class ThriftServiceNode {

	private String name;
	private String type;
	private String url;
	private String accessHost;
	private HostPort hostport;
	private int frameLength;
	private String protocol;

	private String defaultModule;
	private List<ThriftServiceBean> services = new LinkedList<ThriftServiceBean>();
	protected Map<String, String> properties;

	public Map<String, String> getProperties() {
		return properties;
	}

	public void setProperties(Map<String, String> properties) {
		this.properties = properties;
	}
	
	public String getAccessHost() {
		return accessHost;
	}

	public void setAccessHost(String accessHort) {
		this.accessHost = accessHort;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public HostPort getHostport() {
		return hostport;
	}

	public void setHostport(HostPort hostport) {
		this.hostport = hostport;
	}

	public HostPort sureHostPort() {
		if (this.hostport == null)
			this.hostport = new HostPort();
		return this.hostport;
	}

	public void setHost(String host) {
		sureHostPort().setHost(host);
	}

	public void setPort(int port) {
		sureHostPort().setPort(port);
	}

	public void setHostString(String v, int defaultPort) {
		sureHostPort().setHostString(v, defaultPort);
	}

	public int getFrameLength() {
		return frameLength;
	}

	public void setFrameLength(int frameLength) {
		this.frameLength = frameLength;
	}

	public void setFrameSize(String sz) {
		try {
			setFrameLength((int) SizeUtil.convert(sz, 1024, Unit.B));
		} catch (Exception e) {
			throw new IllegalArgumentException("invalid '" + sz + "'", e);
		}
	}

	public String getProtocol() {
		return protocol;
	}

	public void setProtocol(String protocol) {
		this.protocol = protocol;
	}

	public String getDefaultModule() {
		return defaultModule;
	}

	public void setDefaultModule(String defaultModule) {
		this.defaultModule = defaultModule;
	}

	public void setEntry(String entry) {
		ThriftClientConfig cfg = ThriftClientConfig.fromEntry(entry);
		setType(cfg.getType());
		setUrl(cfg.getUrl());
		setDefaultModule(cfg.getModule());
		setFrameLength(cfg.getFrameMaxLength());
		setHostport(cfg.getHost());
		setProtocol(cfg.getProtocol());
	}

	public List<ThriftServiceBean> getServices() {
		return services;
	}

	public void setServices(List<ThriftServiceBean> services) {
		addServices(services);
	}

	public void addServices(List<ThriftServiceBean> services) {
		if (this.services == null)
			this.services = new ArrayList<ThriftServiceBean>();
		for (ThriftServiceBean bean : services) {
			bean.setNode(this);
			this.services.add(bean);
		}
	}

	public void setServiceMap(Map<String, TProcessor> processors) {
		if (processors == null)
			return;
		List<ThriftServiceBean> list = new ArrayList<ThriftServiceBean>();
		for (Map.Entry<String, TProcessor> e : processors.entrySet()) {
			ThriftServiceBean bean = new ThriftServiceBean();
			bean.setProtocol(getProtocol());
			bean.setModule(e.getKey());
			bean.setProcessor(e.getValue());
			list.add(bean);
		}
		addServices(list);
	}

	public String makeUrl() {
		try {
			if (ValueUtil.notEmpty(url)) {
				return url;
			} else {
				String host = ValueUtil.empty(hostport.getHost()) ? accessHost
						: hostport.getHost();
				if (ValueUtil.empty(host)) {
					throw new IllegalStateException(
							"node(host,accessHost) is empty");
				}
				return new URI(type, null, host, hostport.getPort(), null,
						null, null).toString();
			}
		} catch (URISyntaxException e) {
			throw ExceptionUtil.throwRuntime(e);
		}
	}
}
